/**
  ******************************************************************************
  * File Name          : nh3co2.c
  * Description        : Code for terminal applications
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "tskcfg.h"
#include "bsp.h"
#include "nh3co2.h"
#include "sensor.h"

#define NH3_RXBUF_MAXLEN           64
#define NH3RECV_QUE_LENGTH         5
#define NH3RECV_QUE_ITEMSIZE       sizeof(nh3_recvbuftype)

/* NH3&CO2 Sensor task */
TaskHandle_t xNH3CO2_Thd = NULL;
StaticTask_t xNH3CO2_Tcb;
StackType_t  xNH3CO2_Stk[ NH3CO2_STACK_SIZE ];

typedef enum
{
	NH3_HEADER1  = 0u,
	NH3_HEADER2,
	NH3_VOLTAGE1,
	NH3_VOLTAGE2,
	NH3_VOLTAGE3,
	NH3_GASTYPE,
	NH3_GASCONCERT,
	NH3_ALARM,
	NH3_END,
}nh3_recvstattype;

typedef struct
{
	uint8_t temp[4];
	uint8_t v1[4];
	uint8_t v2[4];
	uint8_t v3[4];
	uint8_t type;
	uint8_t nd[4];
	uint8_t alarm;
}nh3_recvbuftype;

typedef struct
{
	nh3_recvstattype stat;
}nh3_recvctrltype;

QueueHandle_t        nh3recv_qhd;
static StaticQueue_t nh3recv_stru;
static uint8_t       nh3recv_area[ NH3RECV_QUE_LENGTH * NH3RECV_QUE_ITEMSIZE ];

 nh3_recvbuftype    nh3_isrbuf;
 nh3_recvbuftype    nh3_rcvbuf;
static nh3_recvctrltype   nh3_rcvctrl;

volatile uint16_t NH3_WarmCount = 600;
volatile uint8_t  NH3_FailCount = 0;

void NH3CO2_RecvIsr(uint8_t dat)
{
	static uint32_t count = 0;
	static char check_recv_sum = 0x00;
	
	switch(nh3_rcvctrl.stat)
	{
		case NH3_HEADER1:
			if(dat == 0xAA)
			{
				nh3_rcvctrl.stat = NH3_HEADER2;
				count = 0;
				check_recv_sum = 0xAA;
			}
			else
			{
				nh3_rcvctrl.stat = NH3_HEADER1;
			}
			break;
		
		case NH3_HEADER2:
			nh3_isrbuf.temp[count++] = dat;
			check_recv_sum += dat;
			
			if(count > 3)
			{
				count = 0;
				nh3_rcvctrl.stat = NH3_VOLTAGE1;
			}
			break;
			
		case NH3_VOLTAGE1:
			nh3_isrbuf.v1[count++] = dat;
			check_recv_sum += dat;
			
			if(count > 3)
			{
				count = 0;
				nh3_rcvctrl.stat = NH3_VOLTAGE2;
			}
			break;
			
		case NH3_VOLTAGE2:
			nh3_isrbuf.v2[count++] = dat;
			check_recv_sum += dat;
			
			if(count > 3)
			{
				count = 0;
				nh3_rcvctrl.stat = NH3_VOLTAGE3;
			}
			break;
		
		case NH3_VOLTAGE3:
			nh3_isrbuf.v3[count++] = dat;
			check_recv_sum += dat;
			
			if(count > 3)
			{
				count = 0;
				nh3_rcvctrl.stat = NH3_GASTYPE;
			}
			break;
		
    case NH3_GASTYPE:
//			if(dat == 0x05)
//			{
				nh3_rcvctrl.stat = NH3_GASCONCERT;
				count = 0;
				check_recv_sum += dat;
//			}
			break;

    case NH3_GASCONCERT:
			nh3_isrbuf.nd[count++] = dat;
			check_recv_sum += dat;
			
			if(count > 3)
			{
				count = 0;
				nh3_rcvctrl.stat = NH3_ALARM;
			}
			break;
			
		case NH3_ALARM:
//			if(dat == 0x00)
//			{
				nh3_rcvctrl.stat = NH3_END;
				count = 0;
				check_recv_sum += dat;
//			}
			break;
		
		case NH3_END:		
			if(dat == check_recv_sum)
			{				
				if(nh3recv_qhd != NULL)
				{
					xQueueSendFromISR(nh3recv_qhd, &nh3_isrbuf, NULL);
				}
			}
			nh3_rcvctrl.stat = NH3_HEADER1;
			break;
		
		default:
			nh3_rcvctrl.stat = NH3_HEADER1;
			break;
	}
}

void NH3CO2_BreakIsr(void)
{
	nh3_rcvctrl.stat = NH3_HEADER1;
}

void vNH3CO2_Task( void * pvParameters )
{
	uint16_t nh3_value = 0;
	
	nh3recv_qhd = xQueueCreateStatic(NH3RECV_QUE_LENGTH,
	                                 NH3RECV_QUE_ITEMSIZE,
	                                 nh3recv_area,
	                                 &nh3recv_stru);
	NH3CO2_BspInit();
	
  NH3_WarmCount = 600;
  
  while(1)
	{
		if(xQueueReceive(nh3recv_qhd, &nh3_rcvbuf, 5000) == pdTRUE)
		{
			nh3_value = ((((uint32_t)nh3_rcvbuf.nd[3])<<24) & 0xFF000000u) + \
			            ((((uint32_t)nh3_rcvbuf.nd[2])<<16) & 0x00FF0000u) + \
			            ((((uint32_t)nh3_rcvbuf.nd[1])<<8)  & 0x0000FF00u) + \
			            nh3_rcvbuf.nd[0];
			
			
			nh3_value /= 1000;
      NH3_WarmCount--;

      SENSOR.Status_NH3 = 0;
			SENSOR.nh3 = nh3_value;
      NH3_FailCount = 0;
		}
		else
		{
			NH3_FailCount++;
		}
		
		if(NH3_FailCount >= 10)
		{
			SENSOR.nh3 = 0;
			NH3_FailCount = 10;
		}
    
    if(NH3_WarmCount < 1)
    {
      break;
    }
	}
  
	while(1)
	{
		if(xQueueReceive(nh3recv_qhd, &nh3_rcvbuf, 5000) == pdTRUE)
		{
			nh3_value = ((((uint32_t)nh3_rcvbuf.nd[3])<<24) & 0xFF000000u) + \
			            ((((uint32_t)nh3_rcvbuf.nd[2])<<16) & 0x00FF0000u) + \
			            ((((uint32_t)nh3_rcvbuf.nd[1])<<8)  & 0x0000FF00u) + \
			            nh3_rcvbuf.nd[0];
			
			nh3_value /= 1000;
      
			if(nh3_value <= 253)
			{
				SENSOR.Status_NH3 = 1;
				SENSOR.nh3 = nh3_value;
        NH3_FailCount = 0;
			}
			else if((nh3_value > 253) && (nh3_value <= 300))
			{
				SENSOR.Status_NH3 = 1;
				SENSOR.nh3 = 253;
        NH3_FailCount = 0;
			}
      else
      {
        SENSOR.Status_NH3 = 0;
				SENSOR.nh3 = 253;
        NH3_FailCount++;
      }
		}
		else
		{
			NH3_FailCount++;
		}
		
		if(NH3_FailCount >= 10)
		{
			SENSOR.nh3 = 0;
			NH3_FailCount = 10;
		}
	}
}
